<script setup lang="ts">
import type { PlusColumn } from 'plus-pro-components'
import type { VxeGridProps, VxePagerEvents } from 'vxe-table'

import {
    operLogExport,
    useGetOperlogList,
    useOperlogClean,
    useOperlogDdeletIds,
} from '@fl/api/joint-api'
import { SearchDescriptions, SearchForm, SearchTable } from '@fl/components'
import { useMessage } from '@fl/hooks/web/use-message'
import { formatTime } from '@fl/utils'
import { cloneDeep } from 'lodash-es'
import { reactive, ref } from 'vue'

import { useDicts } from '../hooks/dict'

const { createConfirmModal, createMessage } = useMessage()
const tableRef = ref()

const { dicts, getDictLabel } = useDicts()

type IState = {
    businessType: string
    operIp: string
    operName: string
    status: string
    timeRange?: any
    title: string
}
const initialState = {
    businessType: '',
    operIp: '',
    operName: '',
    status: '',
    timeRange: [],
    title: '',
}
const state = ref<IState>(cloneDeep(initialState))

const initialPage = {
    currentPage: 1,
    pageSize: 10,
    total: 0,
}
const tablePage = ref(cloneDeep(initialPage))
const param = computed(() => ({
    pageNum: tablePage.value.currentPage,
    pageSize: tablePage.value.pageSize,
    ...state.value,
    businessType: getDictLabel('businessTypeOption', state.value.businessType),
    startTime: state.value.timeRange?.[0]
        ? formatTime(state.value?.timeRange?.[0], 'yyyy-MM-dd 00:00:00')
        : '',
    endTime: state.value.timeRange?.[1]
        ? formatTime(state.value?.timeRange?.[1], 'yyyy-MM-dd 23:59:59')
        : '',
}))
const { mutate: deleteMutateIds } = useOperlogDdeletIds()
const { mutate: cleanMutate } = useOperlogClean()
const { data, isLoading } = useGetOperlogList(param)
const records = ref()

const handlePageChange: VxePagerEvents.PageChange = ({ currentPage, pageSize }) => {
    tablePage.value.currentPage = currentPage
    tablePage.value.pageSize = pageSize
}

watchEffect(() => {
    if (data.value) {
        records.value = cloneDeep(data.value.records)
        tablePage.value.total = data.value.total!
    }
})
// 搜索
function submit(values) {
    state.value = { ...values }
    tablePage.value.currentPage = 1
}
function reset() {
    state.value = cloneDeep(initialState)
    tablePage.value = cloneDeep(initialPage)
}
const columns: PlusColumn[] = [
    {
        label: '操作地址',
        prop: 'operIp',
    },
    {
        label: '系统模块',
        prop: 'title',
    },
    {
        label: '操作人员',
        prop: 'operName',
    },
    {
        label: '类型',
        options: dicts.businessTypeOption,
        prop: 'businessType',
        valueType: 'select',
    },
    {
        label: '状态',
        options: dicts.statusOption,
        prop: 'status',
        valueType: 'select',
    },
    {
        fieldProps: {
            'endPlaceholder': '结束时间',
            'startPlaceholder': '开始时间',
            'type': 'daterange',
            'value-format': 'YYYY-MM-DD',
        },
        label: '操作时间',
        prop: 'timeRange',
        valueType: 'date-picker',
    },
]
const gridOptions = reactive<VxeGridProps>({
    columns: [
        { type: 'checkbox', width: 50 },
        { field: 'id', title: '日志编号' },
        { field: 'title', title: '系统模块' },
        { field: 'businessType', title: '操作类型' },
        { field: 'operName', title: '操作人员' },
        { field: 'operIp', title: '操作地址' },
        { field: 'operLocation', title: '操作地点' },
        { field: 'status', slots: { default: 'status' }, title: '操作状态' },
        { field: 'operTime', title: '操作日期' },
        { field: 'costTime', slots: { default: 'costTime' }, title: '消耗时间' },
        { slots: { default: 'operate' }, title: '操作' },
    ],
})

const detailColumns: PlusColumn[] = [
    {
        descriptionsItemProps: {
            span: 2,
        },
        label: '操作模块:',
        prop: 'title',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 2,
        },
        label: '请求地址:',
        prop: 'operUrl',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 2,
        },
        label: '登录信息:',
        prop: 'sort',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 3,
        },
        label: '请求方式:',
        prop: 'requestMethod',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 3,
        },
        label: '操作方法:',
        prop: 'method',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 3,
        },
        label: '请求参数:',
        prop: 'operParam	',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 3,
        },
        label: '返回参数:',
        prop: 'jsonResult',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 2,
        },
        label: '操作状态:',
        prop: 'status',
        slot: 'status',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 2,
        },
        label: '消耗时间:',
        prop: 'costTime',
        slot: 'costTime',
        width: 180,
    },
    {
        descriptionsItemProps: {
            span: 2,
        },
        label: '操作时间:',
        prop: 'operTime',
        width: 180,
    },
]

const dialogVisible = ref(false)
const detail = ref()
function showDetail(row) {
    dialogVisible.value = true
    detail.value = row
}

// 批量删除
function goMultipleDelete() {
    const $table = tableRef.value?.tableInstance
    if ($table) {
        const selectRecords = $table.getCheckboxRecords()
        const ids = selectRecords.map(item => item.id)
        if (selectRecords.length) {
            createConfirmModal({
                content: '是否确认删除？',
                onError: () => {
                    console.log('操作取消！')
                },
                onSuccess: () => {
                    deleteMutateIds(ids, {
                        onSuccess: () => {
                            createMessage.success('删除成功')
                        },
                    })
                },
            })
        }
        else {
            createMessage.warning('请至少选择一条数据')
        }
    }
}

// 清空
function cleanLog() {
    createConfirmModal({
        content: '是否确认清空？',
        onError: () => {
            console.log('操作取消！')
        },
        onSuccess: async () => {
            const res = await cleanMutate()
            if (res) {
                createMessage.success('清空成功')
            }
        },
    })
}
// exportMutate
async function exportExcel() {
    const result = await operLogExport({ ...unref(param), pageSize: 1000000 })
    const blob = new Blob([result], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
    const objectUrl = URL.createObjectURL(blob)
    location.href = objectUrl
    URL.revokeObjectURL(objectUrl)
}
</script>

<template>
    <ElCard class="mb-20"
            shadow="never"
    >
        <SearchForm v-bind="state"
                    :columns="columns"
                    submit-text="搜索"
                    @reset="reset"
                    @submit="submit"
        />
    </ElCard>

    <ElCard shadow="never">
        <SearchTable ref="tableRef"
                     v-bind="gridOptions"
                     v-model:pager="tablePage"
                     :loading="isLoading"
                     :data="records"
                     @page-change="handlePageChange"
        >
            <template #toolbar_buttons>
                <ElButton @click="goMultipleDelete">
                    删除
                </ElButton>

                <ElButton @click="cleanLog">
                    清空
                </ElButton>

                <ElButton @click="exportExcel">
                    导出
                </ElButton>
            </template>

            <template #operatorType="{ row }">
                {{ getDictLabel("businessTypeOption", row.operatorType) }}
            </template>

            <template #status="{ row }">
                {{ getDictLabel("statusOption", row.status) }}
            </template>

            <template #costTime="{ row }">
                {{ row.costTime }}毫秒
            </template>

            <template #operate="{ row }">
                <el-button text
                           type="primary"
                           @click="showDetail(row)"
                >
                    详细
                </el-button>
            </template>
        </SearchTable>
    </ElCard>

    <el-dialog v-model="dialogVisible"
               title="操作日志详细"
               width="800"
    >
        <div style="max-height: 500px; overflow-y: auto">
            <SearchDescriptions :columns="detailColumns"
                                :data="detail"
            >
                <template #plus-desc-costTime="{ value }">
                    {{ value }}毫秒
                </template>

                <template #plus-desc-status="{ value }">
                    {{ getDictLabel("statusOption", value) }}
                </template>
            </SearchDescriptions>
        </div>
    </el-dialog>
</template>
